#ifndef RP2TRANSFORMATION_H
#define RP2TRANSFORMATION_H

#include "Rp2Matrix3.h"
#include "Rp2Matrix4.h"
#include "Rp2Plane3.h"

namespace Rp2
{
class Transformation
{
public:
	// The default constructor produces the
	// identity transformation.
	Transformation();
	~Transformation();

	// Set the transformation to identity
	void MakeIdentity();

	// Set the scales to 1
	void MakeUnitScale();

	// structure of the transformation
	bool IsIdentity() const;
	bool IsRSMatrix() const;

	// member access
	void SetMatrix(const Matrix3f& rkMatrix);
	const Matrix3f& GetMatrix() const;
	void SetTranslate(const Vector3f& rkTranslate);
	const Vector3f& GetTranslate() const;
	void SetRotate(const Matrix3f& rkRotate);
	const Matrix3f& GetRotate() const;
	void SetScale(const Vector3f rkScale);
	const Vector3f& GetScale() const;
	void SetUniformScale(float fScale);
	const float GetUniformScale() const;
    
	// For M = R*S, the largest value of S in absolute value is returned.
    // For general M, the max-row-sum norm is returned (and is guaranteed to
    // be larger or equal to the largest eigenvalue of S in absolute value).
    float GetNorm () const;

	// compute C = A*B
	void Product(const Transformation& rkA, const Transformation& rkB);

    // Compute Y = X * M + T where X is the input point and Y is the output point.
    Vector3f ApplyForward (const Vector3f& rkInput) const;
    void ApplyForward (int iQuantity, const Vector3f* akInput,
        Vector3f* akOutput) const;

    // Compute X = (Y - T) * M^{-1} where Y is the input point and X is the output
    // point.
    Vector3f ApplyInverse (const Vector3f& rkInput) const;
    void ApplyInverse (int iQuantity, const Vector3f* akInput,
        Vector3f* akOutput) const;

    // Compute Y = X * M where X is the input vector and Y is the output vector.
    Vector3f ApplyForwardVector (const Vector3f& rkInput) const;

    // Compute X = Y * M^{-1} where Y is the input vector and X is the output
    // vector.
    Vector3f InvertVector (const Vector3f& rkInput) const;

	void GetHomogeneous(Matrix4f& rkM) const;

private:
	friend class Spatial;

	Matrix3f m_kMatrix;
	Vector3f m_kTranslate;
	Vector3f m_kScale;

	bool m_bIsIdentity;
	bool m_bIsRSMatrix;
	bool m_bIsUniformScale;
};

#include "Rp2Transformation.inl"
}

#endif